﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using SelfService.Controllers.Apis;
using SelfService.Model;
using SelfService.Model.Interface;
using SelfService.Model.Models;
using WalkingTec.Mvvm.Core;

namespace SelfService.Tasks;

/// <summary>
/// 社保冲正服务
/// </summary>
[Display(Name = "社保冲正")]
public class SocialReverseTask : BaseTask
{
    private readonly WTMContext _context;
    private readonly IMemoryCache _memoryCache;

    public SocialReverseTask(WTMContext context, IMemoryCache memoryCache) : base(context)
    {
        _context = context;
        _memoryCache = memoryCache;
    }

    public override async Task<bool> Process()
    {
        this.Logger("开始社保冲正", ActionLogTypesEnum.Job);
        var dc = _context.DC;
        var list = await dc.Set<SysPrescription>()
            .AsNoTracking()
            .Where(e => e.SocialSecurityStatus == SocialSecurityType.预结算)
            .Where(e => e.UpdateTime < DateTime.Now.AddMinutes(-10) && e.UpdateTime > DateTime.Now.AddHours(-4))
            .Select(e => e.ID)
            .ToListAsync();
        foreach (var prescriptionId in list)
        {
            try
            {
                var slim = await _memoryCache.GetOrCreateAsync($"{nameof(SysSocialSecurityController)}:{nameof(SysSocialSecurityController.Reverse)}:{prescriptionId}", entry =>
                {
                    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1);
                    return Task.FromResult(new SemaphoreSlim(1, 1));
                });
                if (!await slim.WaitAsync(TimeSpan.FromSeconds(3)))
                {
                    continue;
                }
                try
                {
                    var prescription = dc.Set<SysPrescription>()
                        .Include(e => e.Patient)
                        .FirstOrDefault(e => e.ID == prescriptionId);
                    if (prescription == null) continue;
                    if (prescription.Status != SysOrderStatus.未缴费 || prescription.SocialSecurityStatus != SocialSecurityType.预结算)
                    {
                        this.Logger("单据状态异常, 无法冲正", ActionLogTypesEnum.Exception);
                        continue;
                    }
                    //调用HIS接口
                    ISocialSecurityOrder service;
                    try
                    {
                        var scope = _context.ServiceProvider.CreateScope();
                        service = scope.ServiceProvider.GetRequiredService<ISocialSecurityOrder>();
                    }
                    catch (Exception)
                    {
                        this.Logger("服务端没有启用社保业务", ActionLogTypesEnum.Exception);
                        continue;
                    }
                    var data = service.CancelPay(prescription).Result;
                    if (data.Code == 200)
                    {
                        this.Logger($"医保撤销结算, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Debug);
                        prescription.SocialSecurityStatus = SocialSecurityType.冲正成功;
                        prescription.UpdateBy = "service";
                        prescription.UpdateTime = DateTime.Now;
                        await dc.SaveChangesAsync();
                        continue;
                    }
                    else
                    {
                        this.Logger($"医保撤销结算失败, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Exception);
                        prescription.SocialSecurityStatus = SocialSecurityType.冲正失败;
                        prescription.ErrorMessage = data.Message;
                        prescription.UpdateBy = "service";
                        prescription.UpdateTime = DateTime.Now;
                        await dc.SaveChangesAsync();
                        this.Logger($"医保撤销结算失败. {data.Message}", ActionLogTypesEnum.Exception);
                    }
                }finally
                {
                    slim.Release();
                }
            }
            catch (Exception e)
            {
                this.Logger($"医保撤销结算异常:{e.Message} | StackTrace: {e.StackTrace}", ActionLogTypesEnum.Exception);
                continue;
            }
        }
        return true;
    }
}